package com.gaga.console.base.config;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.gaga.common.path.ApiPath;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.FileNotFoundException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

/**
 *
 */
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {


    private String path = URLDecoder.decode(ResourceUtils.getURL("classpath:").getPath());
    ;

    public SaTokenConfigure() throws FileNotFoundException {
    }

    /**
     * 注册 [Sa-Token 全局过滤器]
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()

                // 指定 [拦截路由] 与 [放行路由]
                .addInclude("/**").addExclude("/favicon.ico")
                // 认证函数: 每次请求执行
                .setAuth(obj -> {
                    SaManager.getLog().debug("----- 请求path={}  提交token={}", SaHolder.getRequest().getRequestPath(), StpUtil.getTokenValue());
                })
                // 异常处理函数：每次认证函数发生异常时执行此函数
                .setError(e -> {
                    return SaResult.error(e.getMessage());
                })
                // 前置函数：在每次认证函数之前执行
                .setBeforeAuth(obj -> {
                    SaHolder.getResponse()

                            // 允许指定域访问跨域资源
                            .setHeader("Access-Control-Allow-Origin", "*")
                            // 允许所有请求方式
                            .setHeader("Access-Control-Allow-Methods", "*")
                            // 允许的header参数
                            .setHeader("Access-Control-Allow-Headers", "*")
                            // 有效时间
                            .setHeader("Access-Control-Max-Age", "3600");

                    // 如果是预检请求，则立即返回到前端
                    SaRouter.match(SaHttpMethod.OPTIONS).back();
                });
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .exposedHeaders("*");
    }

    @SneakyThrows
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        String staticMapping = "/files/**";
        String localDirectory = "file:" + path;

        /** 文件映射 */
        registry.addResourceHandler(staticMapping).addResourceLocations(localDirectory);

        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");

        WebMvcConfigurer.super.addResourceHandlers(registry);
    }

    /**
     * 放行的url
     *
     * @return
     */
    public static List<String> notLogin() {

        List<String> allows = new ArrayList<>();
        allows.add("/" + ApiPath.ROOT + "/common/auth/**");
        allows.add("/" + ApiPath.ROOT + "/app/version/**");
        //放行所有
//        allows.add("/" + ApiPath.ROOT + "/**");

        //swagger资源放行
        allows.add("/v2/**");
        allows.add("/v3/**");
        allows.add("/*.html");
        allows.add("/swagger-ui.html/**");
        allows.add("/swagger-ui/**");
        allows.add("/doc.html/**");
        allows.add("/api-docs-ext/**");
        allows.add("/swagger-resources/**");
        allows.add("/webjars/**");
        allows.add("/favicon.ico");
        allows.add("/error");

        return allows;
    }

}
